<script lang="ts" setup>
import type { TreeProps } from 'ant-design-vue';

import { nextTick, onMounted, ref } from 'vue';

import { message } from 'ant-design-vue';

const expandedKeys = ref<string[]>([]);
const selectedKeys = ref<string[]>([]);
const treeData = ref<any[]>([]);
const loading = ref<boolean>(false);
const renderTime = ref<string>('0');
const generationTime = ref<string>('0');
const isAllExpanded = ref<boolean>(false);
const expandLoading = ref<boolean>(false);

// 定义树节点类型
interface TreeNode {
  title: string;
  key: string;
  children?: TreeNode[];
  isLeaf?: boolean;
}

// 获取所有节点的key
const getAllNodeKeys = (nodes: TreeNode[]): string[] => {
  const keys: string[] = [];
  const traverse = (items: TreeNode[]) => {
    items.forEach((item) => {
      keys.push(item.key);
      if (item.children && item.children.length > 0) {
        traverse(item.children);
      }
    });
  };

  traverse(nodes);
  return keys;
};

// 展开或折叠所有节点
const toggleExpandAll = async () => {
  if (treeData.value.length === 0 || treeData.value.length <= 3) {
    message.warning('请先生成数据');
    return;
  }

  expandLoading.value = true;
  const startTime = performance.now();

  // 等待DOM更新
  await nextTick();

  if (isAllExpanded.value) {
    // 折叠所有
    expandedKeys.value = [];
    isAllExpanded.value = false;
  } else {
    // 展开所有
    expandedKeys.value = getAllNodeKeys(treeData.value);
    isAllExpanded.value = true;
  }

  // 等待DOM更新
  await nextTick();

  const endTime = performance.now();
  expandLoading.value = false;

  message.success(
    `${isAllExpanded.value ? '展开' : '折叠'}所有节点完成，耗时: ${(endTime - startTime).toFixed(2)}毫秒`,
  );
};

// 生成测试数据
const generateDataset = async (scale: number) => {
  loading.value = true;
  const startTime = performance.now();

  // 重置展开状态
  expandedKeys.value = [];
  isAllExpanded.value = false;

  // 根据scale参数调整数据量
  let firstLevelCount = 10;
  let secondLevelCount = 10;
  let thirdLevelCount = 10;

  // 分别设置不同规模的数据量
  switch (scale) {
    case 1: {
      // 1000条数据: 10x10x10
      firstLevelCount = 10;
      secondLevelCount = 10;
      thirdLevelCount = 10;

      break;
    }
    case 2: {
      // 5000条数据: 50x10x10
      firstLevelCount = 50;
      secondLevelCount = 10;
      thirdLevelCount = 10;

      break;
    }
    case 3: {
      // 1万条数据: 100x10x10
      firstLevelCount = 100;
      secondLevelCount = 10;
      thirdLevelCount = 10;

      break;
    }
    case 4: {
      // 10万条数据: 100x100x10
      firstLevelCount = 100;
      secondLevelCount = 100;
      thirdLevelCount = 10;

      break;
    }
    case 5: {
      // 50万条数据: 100x100x50
      firstLevelCount = 100;
      secondLevelCount = 100;
      thirdLevelCount = 50;

      break;
    }
    case 6: {
      // 100万条数据: 100x100x100
      firstLevelCount = 100;
      secondLevelCount = 100;
      thirdLevelCount = 100;

      break;
    }
    // No default
  }

  const totalCount = firstLevelCount * secondLevelCount * thirdLevelCount;

  // 显示大数据量的警告
  if (totalCount >= 100_000) {
    message.warning(
      `即将生成${totalCount}条数据，可能会导致浏览器卡顿，请耐心等待`,
    );
    await new Promise((resolve) => setTimeout(resolve, 1000));
  }

  const data: TreeNode[] = [];
  // 创建一级节点
  for (let i = 0; i < firstLevelCount; i++) {
    const firstLevelNode: TreeNode = {
      title: `一级节点-${i}`,
      key: `${i}`,
      children: [],
    };

    // 每个一级节点创建二级节点
    for (let j = 0; j < secondLevelCount; j++) {
      const secondLevelNode: TreeNode = {
        title: `二级节点-${i}-${j}`,
        key: `${i}-${j}`,
        children: [],
      };

      // 每个二级节点创建三级节点
      for (let k = 0; k < thirdLevelCount; k++) {
        if (secondLevelNode.children) {
          secondLevelNode.children.push({
            title: `三级节点-${i}-${j}-${k}`,
            key: `${i}-${j}-${k}`,
            isLeaf: true,
          });
        }
      }

      if (firstLevelNode.children) {
        firstLevelNode.children.push(secondLevelNode);
      }
    }

    data.push(firstLevelNode);
  }

  const generationEndTime = performance.now();
  generationTime.value = (generationEndTime - startTime).toFixed(2);

  // 赋值数据到tree组件
  treeData.value = data;

  // 使用nextTick等待DOM更新
  await nextTick();
  const renderEndTime = performance.now();
  renderTime.value = (renderEndTime - generationEndTime).toFixed(2);

  loading.value = false;

  message.success(
    `数据处理完成！\n总节点数：${totalCount}条\n数据生成耗时: ${generationTime.value}毫秒\n渲染耗时: ${renderTime.value}毫秒\n总耗时: ${(renderEndTime - startTime).toFixed(2)}毫秒`,
  );
};

const onLoadData: TreeProps['loadData'] = (treeNode) => {
  // eslint-disable-next-line no-console
  console.log('onLoadData:', treeNode);
  return new Promise<void>((resolve) => {
    if (treeNode.dataRef && treeNode.dataRef.children) {
      resolve();
      return;
    }
    setTimeout(() => {
      if (treeNode.dataRef) {
        treeNode.dataRef.children = [
          { title: 'Child Node', key: `${treeNode.eventKey}-0` },
        ];
      }
      treeData.value = treeData.value ? [...treeData.value] : [];
      resolve();
    }, 1000);
  });
};

// 初始加载少量数据
onMounted(() => {
  treeData.value = [
    { title: 'Expand to load', key: '0' },
    { title: 'Expand to load', key: '1' },
    { title: 'Tree Node', key: '2', isLeaf: true },
  ];
});
</script>

<template>
  <div class="p-5">
    <a-card class="mb-5">
      <div class="mb-4">
        <div class="mb-2">基础数据量</div>
        <a-button-group class="mb-4">
          <a-button
            type="primary"
            @click="generateDataset(1)"
            :loading="loading"
          >
            生成1000条数据
          </a-button>
          <a-button
            type="primary"
            @click="generateDataset(2)"
            :loading="loading"
          >
            生成5000条数据
          </a-button>
          <a-button
            type="primary"
            @click="generateDataset(3)"
            :loading="loading"
          >
            生成1万条数据
          </a-button>
          <a-button
            type="primary"
            @click="generateDataset(4)"
            :loading="loading"
          >
            生成10万条数据
          </a-button>
        </a-button-group>

        <div class="mb-2">大数据量（谨慎操作）</div>
        <a-button-group class="mb-4">
          <a-button
            type="primary"
            danger
            @click="generateDataset(5)"
            :loading="loading"
          >
            生成50万条数据
          </a-button>
          <a-button
            type="primary"
            danger
            @click="generateDataset(6)"
            :loading="loading"
          >
            生成100万条数据
          </a-button>
        </a-button-group>

        <div>
          <a-button
            type="default"
            @click="toggleExpandAll"
            :loading="expandLoading"
            :disabled="treeData.length <= 3"
          >
            {{ isAllExpanded ? '折叠所有节点' : '展开所有节点' }}
          </a-button>
        </div>
      </div>

      <div v-if="generationTime !== '0'" class="mb-4">
        <a-descriptions title="性能测试结果" bordered>
          <a-descriptions-item label="数据生成耗时">
            {{ generationTime }} 毫秒
          </a-descriptions-item>
          <a-descriptions-item label="渲染耗时">
            {{ renderTime }} 毫秒
          </a-descriptions-item>
          <a-descriptions-item label="总耗时">
            {{ (Number(generationTime) + Number(renderTime)).toFixed(2) }}
            毫秒
          </a-descriptions-item>
        </a-descriptions>
      </div>

      <a-spin :spinning="loading">
        <a-tree
          v-model:expanded-keys="expandedKeys"
          v-model:selected-keys="selectedKeys"
          :load-data="onLoadData"
          :tree-data="treeData"
          checkable
          :height="500"
          :virtual="true"
          :item-height="28"
        />
      </a-spin>
    </a-card>
  </div>
</template>

<style scoped></style>
